package com.zx.sms.common.util;

import cn.hutool.core.util.ObjectUtil;
import com.zx.sms.connect.manager.EndpointConnector;
import com.zx.sms.connect.manager.EndpointEntity;
import com.zx.sms.connect.manager.EndpointManager;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.util.concurrent.GenericFutureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ChannelUtil {

	private static final Logger logger = LoggerFactory.getLogger(ChannelUtil.class);
	/**
	 * 同步发送消息到端口，发送完成才返回。
	 *
	 * 方法会阻塞线程，直到消息发送完成
	 */
	public static ChannelFuture asyncWriteToEntity(final EndpointEntity entity, final Object msg) {

		EndpointConnector connector = EndpointManager.INS.getEndpointConnector(entity);
		return asyncWriteToEntity(connector,msg,null);
	}

	public static ChannelFuture asyncWriteToEntity(final String entity, final Object msg) {

		EndpointConnector connector = EndpointManager.INS.getEndpointConnector(entity);
		return asyncWriteToEntity(connector,msg,null);
	}

	public static ChannelFuture asyncWriteToEntity(final EndpointEntity entity, final Object msg,GenericFutureListener listner) {

		EndpointConnector connector = EndpointManager.INS.getEndpointConnector(entity);
		return asyncWriteToEntity(connector,msg,listner);
	}

	public static ChannelFuture asyncWriteToEntity(final String entity, final Object msg,GenericFutureListener listner) {

		EndpointConnector connector = EndpointManager.INS.getEndpointConnector(entity);
		return asyncWriteToEntity(connector,msg,listner);
	}

	private static ChannelFuture asyncWriteToEntity(EndpointConnector connector, final Object msg , GenericFutureListener listner )  {
		if (ObjectUtil.isNull(connector)) {
			logger.error("发送数据失败，连接已断开，msg={}",msg);
			return null;
		}

		Channel ch=null;
		for (int i = 0; i < 5; i++) {// 解决 连接 登录 还未 成功，就发送数据问题
			ch = connector.fetch();
			// 端口上还没有可用连接
			if (ch == null){
				try {
					Thread.currentThread().sleep((i) * 50l);// zhangzhiliang 可以根据网络情况，调整等待时间
					//logger.info("等待登录，sleep={}", (i) * 50l);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				continue;
			}else {
				if (ch.isActive() && ch.isWritable()) {

					ChannelFuture future = ch.writeAndFlush(msg);
					if(listner==null){
						future.addListener(new GenericFutureListener<ChannelFuture>() {
							@Override
							public void operationComplete(ChannelFuture future) throws Exception {
								// 如果发送消息失败，记录失败日志
								if (!future.isSuccess()) {
									StringBuilder sb = new StringBuilder();
									sb.append("SendMessage ").append(msg.toString()).append(" Failed. ");
									logger.error(sb.toString(), future.cause());
								}
							}
						});
					}else{
						future.addListener(listner);
					}

					return future;
				}
				break;
			}
		}

		if (null == ch){// 解决 连接 登录还未 成功，就发送数据问题
			logger.error("尚未登录成功，发送数据失败，msg={}",msg);
		}
		return null;
	}


}
